library(tidyverse) # For data wrangling
library(ggplot2) # Data visualization
library(readxl) # To read Excel files
library(kableExtra) # For data tables
library(ggplot2) # For data visualization
library(ggtext) # For formatting text in ggplot2
library(showtext) # For custom fonts in ggplot2
library(stringr) # For string manipulation
A dot plot of public acceptability of domestic violence in Cambodia between 2005 and 2009
How to use {ggplot2} to create a dot plot to visualize changes over time
Overview
According to official data from the National Institute of Statistics of Cambodia, in 2009 about 77 percent of Cambodians aged 15–49 considered it acceptable for a man to curse his wife. Although this figure is high, it represents a decrease of about 16 percentage points compared to the previous estimate from 2005. Analyzing these changes is important for gaining a better understanding of the phenomenon of violence against women and girls.
One of the most effective ways to visualize these changes over time is through dot plots. In this post, we will use the {ggplot2} package in R to create a dot plot that illustrates how public acceptance of domestic violence in Cambodia changed between 2005 and 2009.
Set-up
Load necessary libraries for data processing and visualization.
Loading data
Data comes from the report “Women and Men in Cambodia” produced by the National Institute of Statistics of the Ministry of Planning. This document provides insights into the situation of women and men in different spheres of life, including health, education, labour, decision making, and violence. The data used in this post is available in the table “Public Acceptability of Domestic Violence between 2005 and 2009” in section “VIOLENCE AGAINST WOMEN”. Report can be found here.
I extracted the data from the report and created an Excel file that can be found here
acceptability_violence <- read_excel("acceptability-violence-cambodia.xlsx")
This information looks like this:
acceptability_violence |>
kbl(
caption = "Public Acceptability of Domestic Violence in Cambodia between 2005 and 2009"
) |>
kable_paper("hover", full_width = F)
Action | 2005 | 2009 |
---|---|---|
Cursing | 93 | 77 |
Pushing, shaking, or throwing something | 74 | 46 |
Knocking on the head | 69 | 36 |
Tying up or hitting | 40 | 18 |
Threatening with a knife gun or another weapon | 37 | 13 |
Burning or choking | 24 | 10 |
Throwing acid | 10 | 9 |
I use the pivot_longer()
function in the {tidyverse} package to reshape the data to a long format, required for this plot.
acceptability_violence <- acceptability_violence |>
pivot_longer(!Action, names_to = "Year", values_to = "Percentage")
Now the data looks like this:
acceptability_violence |>
kbl(caption = "Public Acceptability of Domestic Violence in Cambodia between 2005 and 2009") |>
kable_paper("hover", full_width = F)
Action | Year | Percentage |
---|---|---|
Cursing | 2005 | 93 |
Cursing | 2009 | 77 |
Pushing, shaking, or throwing something | 2005 | 74 |
Pushing, shaking, or throwing something | 2009 | 46 |
Knocking on the head | 2005 | 69 |
Knocking on the head | 2009 | 36 |
Tying up or hitting | 2005 | 40 |
Tying up or hitting | 2009 | 18 |
Threatening with a knife gun or another weapon | 2005 | 37 |
Threatening with a knife gun or another weapon | 2009 | 13 |
Burning or choking | 2005 | 24 |
Burning or choking | 2009 | 10 |
Throwing acid | 2005 | 10 |
Throwing acid | 2009 | 9 |
Dot plot design
I create a custom theme for the dot plot and apply the font “Jacques Francois”. More font alternatives can be found here.
# Add custom font
font_add_google("Jacques Francois", "Jacques Francois")
showtext_auto()
# Custom theme for the waffle chart
theme_dot_plot <- function() {
theme_minimal(
base_family = "Jacques Francois" # Base theme with custom font
) +
# Custom theme settings
theme(
# remove grid lines
panel.grid = element_line(
size = 0.5,
colour = "white"
),
# Axis settings
axis.line = element_blank(),
axis.title.y = element_blank(),
axis.text.y = element_text(
color = "black",
face = "bold",
size = 16
),
axis.title.x = element_text(
color = "black",
face = "bold",
size = 16
),
axis.text.x = element_text(
color = "black",
face = "bold",
size = 16
),
# Title settings
plot.title.position = "plot", # Position of the title
plot.title = element_text(
color = "black",
face = "bold",
size = 24,
margin = margin(5, 0, 5, 0) # Top, right, bottom, left
),
# Subtitle settings
plot.subtitle = element_text(
color = "grey20",
face = "italic",
size = 20,
margin = margin(0, 0, 10, 0)
),
# Legend settings
legend.position = "top",
legend.title = element_blank(),
legend.spacing.x = unit(0.2, "cm"),
legend.key.spacing = unit(0.5, "cm"), # Spacing between legend keys
legend.text = element_text(
margin = margin(5, 2, 5, 0),
face = "bold",
color = "black",
size = 16
),
legend.direction = "horizontal",
legend.byrow = FALSE,
# Caption settings
plot.caption = element_text(
margin = margin(40, 0, 0, 0), # Top, right, bottom, left
color = "black",
size = 16
),
plot.caption.position = "plot",
plot.background = element_rect(
color = "#FBB4AE",
fill = "#FBB4AE"
),
plot.margin = margin(20, 40, 20, 40)
)
}
title_chart <- "Public acceptability of domestic violence in Cambodia"
subtitle_chart <- "Between 2005 and 2009, the share of people who tolerate violence has decreased"
caption_chart <- "Cambodia Key Gender Statistics, 2015 \nChart created by Juan Torres Munguía"
# Set the resolution of the image 320 dpi is for high-quality images ("retina")
showtext_opts(dpi = 320)
Finally, I create the dot plot using geom_line()
and geom_point()
functions from the {ggplto2} package.
dot_plot_acceptability <- acceptability_violence |>
ggplot(
aes(x = Percentage,
y = Action)
) +
geom_line(
aes(group = Action),
linewidth = 1.5,
color = "#737373"
) +
geom_point(
aes(color = Year),
size = 6
) +
scale_colour_manual(
values = c("#084081", "#2B8CBE")
) +
labs(
title = title_chart,
subtitle = subtitle_chart,
caption = caption_chart,
) +
scale_x_continuous(
limits = c(0, 100)
) +
scale_y_discrete(
# Wrap y-axis labels to a width of 32 characters
labels = function(x) str_wrap(x, width = 32)
) +
theme_dot_plot()
Finally, I export the plot using a 320-dpi resolution for high-quality (“retina”)
dot_plot_acceptability
showtext_opts(dpi = 320)
ggsave(
"cambodia-domestic-violence-dot-plot.png",
dpi = 320,
width = 12,
height = 9,
units = "in"
)
# Turn off the showtext functionality
showtext_auto(FALSE)
Citation
@online{torres munguía2025,
author = {Torres Munguía, Juan Armando},
title = {A Dot Plot of Public Acceptability of Domestic Violence in
{Cambodia} Between 2005 and 2009},
date = {2025-06-18},
url = {https://juan-torresmunguia.netlify.app/blog/posts/cambodia-acceptability-violence-dot-plot},
langid = {en}
}